package com.xu.ai.model.dashscope.controller;

import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.stream.Collectors;

import com.alibaba.cloud.ai.dashscope.api.DashScopeAudioSpeechApi;
import com.alibaba.cloud.ai.dashscope.api.DashScopeAudioTranscriptionApi;
import com.alibaba.cloud.ai.dashscope.audio.DashScopeAudioSpeechOptions;
import com.alibaba.cloud.ai.dashscope.audio.DashScopeAudioTranscriptionOptions;
import com.alibaba.cloud.ai.dashscope.audio.transcription.AudioTranscriptionModel;
import com.alibaba.cloud.ai.dashscope.spec.DashScopeModel;
import org.springframework.ai.audio.transcription.AudioTranscription;
import org.springframework.ai.audio.transcription.AudioTranscriptionPrompt;
import org.springframework.ai.audio.transcription.AudioTranscriptionResponse;
import org.springframework.ai.audio.tts.TextToSpeechModel;
import org.springframework.ai.audio.tts.TextToSpeechPrompt;
import org.springframework.ai.audio.tts.TextToSpeechResponse;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

/**
 * 语音模型 controller
 *
 * @author xuguan
 * @since 2025/11/10
 * @see DashScopeModel.AudioModel
 */
@RestController
@RequestMapping("/api/model/dashscope/audio")
public class AudioController {

	// 语音合成模型
	private final TextToSpeechModel textToSpeechModel;
	// 语音识别模型
	private final AudioTranscriptionModel audioTranscriptionModel;
	private final ResourceLoader resourceLoader;

	public AudioController(TextToSpeechModel textToSpeechModel,
						   AudioTranscriptionModel audioTranscriptionModel,
						   ResourceLoader resourceLoader) {

		this.textToSpeechModel = textToSpeechModel;
		this.audioTranscriptionModel = audioTranscriptionModel;
		this.resourceLoader = resourceLoader;
	}

	/**
	 * CosyVoice语音合成
	 */
	@GetMapping(path = "/cosyVoice-speech-synthesis")
	public void cosyVoiceSpeechSynthesis() {
		DashScopeAudioSpeechOptions options = DashScopeAudioSpeechOptions.builder()
				.model("cosyvoice-v1")
				.voice("longwan")
				.responseFormat(DashScopeAudioSpeechApi.ResponseFormat.MP3)
				.build();

		final TextToSpeechResponse response = this.textToSpeechModel.call(new TextToSpeechPrompt("举头望明月,低头思故乡", options));

		final Resource resource = resourceLoader.getResource("classpath:");
		String filename = "audio_" + currentDateTimeFormat() + ".mp3";
		try (FileOutputStream fos = new FileOutputStream(resource.getURL().getPath() + filename)) {
			// ByteBuffer byteBuffer = synthesisResponse.getResult().getOutput().getAudio();
			fos.write(response.getResult().getOutput());
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Sambert语音合成
	 */
	@GetMapping(path = "/sambert-speech-synthesis")
	public void sambertSpeechSynthesis() {
		DashScopeAudioSpeechOptions options = DashScopeAudioSpeechOptions.builder()
			.model("sambert-zhichu-v1")
			.voice("知厨")
			.speed(1.0)
			.responseFormat(DashScopeAudioSpeechApi.ResponseFormat.MP3)
			.build();

		TextToSpeechPrompt prompt = new TextToSpeechPrompt("""
			举头望明月,低头思故乡""", options);

		TextToSpeechResponse textToSpeechResponse = this.textToSpeechModel.call(prompt);

		final Resource resource = resourceLoader.getResource("classpath:");
		String filename = "audio_" + currentDateTimeFormat() + ".mp3";
		try (FileOutputStream fos = new FileOutputStream(resource.getURL().getPath() + filename)) {
			// ByteBuffer byteBuffer = synthesisResponse.getResult().getOutput().getAudio();
			fos.write(textToSpeechResponse.getResult().getOutput());
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		// SpeechSynthesisPrompt prompt = new SpeechSynthesisPrompt("今天天气怎么样？", options);

		// SpeechSynthesisResponse synthesisResponse = this.speechSynthesisModel.call(prompt);
		//
		// final Resource resource = resourceLoader.getResource("classpath:");
		// String filename = "audio_" + currentDateTimeFormat() + ".mp3";
		// try (FileOutputStream fos = new FileOutputStream(resource.getURL().getPath() + filename)) {
		// 	ByteBuffer byteBuffer = synthesisResponse.getResult().getOutput().getAudio();
		// 	fos.write(byteBuffer.array());
		// } catch (IOException e) {
		// 	throw new RuntimeException(e);
		// }
	}

	/**
	 * paraformer-v1语音识别
	 */
	@GetMapping(path = "/paraformer-v1-audio-transcription")
	public String paraformerV1AudioTranscription() {
		DashScopeAudioTranscriptionOptions options = DashScopeAudioTranscriptionOptions.builder()
			.model("paraformer-v1")
			.build();

		final Resource resource = resourceLoader.getResource("https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav");
		AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(resource, options);

		return audioTranscriptionModel.call(resource);
	}

	/**
	 * paraformer-v2语音识别
	 */
	@GetMapping(path = "/paraformer-v2-audio-transcription")
	public String paraformerV2AudioTranscription() {
		DashScopeAudioTranscriptionOptions options = DashScopeAudioTranscriptionOptions.builder()
			.model("paraformer-v2")
			.build();

		final Resource resource = resourceLoader.getResource("https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav");
		AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(resource, options);

		final AudioTranscriptionResponse transcriptionResponse = audioTranscriptionModel.call(prompt);
		final String text = transcriptionResponse.getResult().getOutput();
		return text;
	}

	/**
	 * fun-asr语音识别
	 */
	@GetMapping(path = "/fun-asr-audio-transcription")
	public String funAsrAudioTranscription() {
		DashScopeAudioTranscriptionOptions options = DashScopeAudioTranscriptionOptions.builder()
			.model("fun-asr")
			.build();

		final Resource resource = resourceLoader.getResource("https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav");
		AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(resource, options);

		final AudioTranscriptionResponse transcriptionResponse = audioTranscriptionModel.call(prompt);
		final String text = transcriptionResponse.getResult().getOutput();
		return text;
	}

	/**
	 * paraformer-realtime-v1实时语音识别
	 */
	@GetMapping(path = "/paraformer-realtime-v1-audio-transcription")
	public Flux<String> paraformerRealtimeV1ReAudioTranscription() {
		DashScopeAudioTranscriptionOptions options = DashScopeAudioTranscriptionOptions.builder()
			.model("paraformer-realtime-v1")
			.sampleRate(16000)
			.build();

		final Resource resource = resourceLoader.getResource("https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav");
		AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(resource, options);

		final Flux<AudioTranscriptionResponse> transcriptionResponse = audioTranscriptionModel.stream(prompt);
		final Flux<String> flux = transcriptionResponse
			.map(AudioTranscriptionResponse::getResult)
			.map(transcription -> {
				final String output = transcription.getOutput();
				return output == null ? "" : output;
			});
		return flux;
	}

	/**
	 * paraformer-realtime-v2实时语音识别
	 */
	@GetMapping(path = "/paraformer-realtime-v2-audio-transcription")
	public String paraformerRealtimeV2AudioTranscription() {
		DashScopeAudioTranscriptionOptions options = DashScopeAudioTranscriptionOptions.builder()
			.model("paraformer-realtime-v2")
			.format(DashScopeAudioTranscriptionApi.AudioFormat.PCM)
			.sampleRate(16000)
			.build();

		final Resource resource = resourceLoader.getResource("classpath:audio.mp3");
		return audioTranscriptionModel.stream(resource, options).collect(Collectors.joining()).block();
	}

	/**
	 * fun-asr-realtime实时语音识别
	 */
	@GetMapping(path = "/fun-asr-realtime-audio-transcription", produces = "text/html;charset=UTF-8")
	public Flux<String> funAsrRealtimeAudioTranscription() {
		DashScopeAudioTranscriptionOptions options = DashScopeAudioTranscriptionOptions.builder()
			.model("fun-asr-realtime")
			.format(DashScopeAudioTranscriptionApi.AudioFormat.PCM)
			.sampleRate(16000)
			.build();

		final Resource resource = resourceLoader.getResource("https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav");
		AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(resource, options);

		final Flux<AudioTranscriptionResponse> transcriptionResponse = audioTranscriptionModel.stream(prompt);
		final Flux<String> flux = transcriptionResponse
			.map(AudioTranscriptionResponse::getResult)
			.map(AudioTranscription::getOutput);
		return flux;
	}

	/**
	 * gummy-realtime-v1实时语音识别
	 */
	@GetMapping(path = "/gummy-realtime-v1-audio-transcription", produces = "text/html;charset=UTF-8")
	public Flux<String> gummyRealtimeV1AudioTranscription() {
		DashScopeAudioTranscriptionOptions options = DashScopeAudioTranscriptionOptions.builder()
			.model("gummy-realtime-v1")
			.format(DashScopeAudioTranscriptionApi.AudioFormat.PCM)
			.sampleRate(16000)
			.build();

		final Resource resource = resourceLoader.getResource("https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav");
		AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(resource, options);

		final Flux<AudioTranscriptionResponse> transcriptionResponse = audioTranscriptionModel.stream(prompt);
		final Flux<String> flux = transcriptionResponse
			.map(AudioTranscriptionResponse::getResult)
			.map(transcription -> {
				final String output = transcription.getOutput();
				return output == null ? "" : output;
			});
		return flux;
	}

	/**
	 * gummy-chat-v1短语音识别
	 */
	@GetMapping(path = "/gummy-chat-v1-audio-transcription", produces = "text/html;charset=UTF-8")
	public Flux<String> gummyChatV1AudioTranscription() {
		DashScopeAudioTranscriptionOptions options = DashScopeAudioTranscriptionOptions.builder()
			.model("gummy-chat-v1")
			.format(DashScopeAudioTranscriptionApi.AudioFormat.PCM)
			.sampleRate(16000)
			.build();

		final Resource resource = resourceLoader.getResource("https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav");
		AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(resource, options);

		final Flux<AudioTranscriptionResponse> transcriptionResponse = audioTranscriptionModel.stream(prompt);
		final Flux<String> flux = transcriptionResponse
			.map(AudioTranscriptionResponse::getResult)
			.map(AudioTranscription::getOutput);
		return flux;
	}

	private String currentDateTimeFormat() {
		return DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(LocalDateTime.now());
	}
}
